package main

import (
	"fmt"
	"sync"
	"time"
)

func Add(a, b int) int {
	return a + b
}

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Printf("字符  %s:%d \n", s, i)
	}
}

var counter int

func MutexDemo() {
	var wg sync.WaitGroup
	var mu sync.Mutex
	wg.Add(100000)

	for i := 0; i < 100000; i++ {
		go func() {
			mu.Lock()
			for j := 0; j < 10000; j++ {
				counter++
			}
			mu.Unlock()
			wg.Done()
		}()

	}
	wg.Wait()
	fmt.Println("Counter:", counter)
}

const capacity = 5

var queue []int
var mu sync.Mutex

var cond = sync.NewCond(&mu)

func main() {
	//go say("sync world ")
	//say("hello")
	//MutexDemo()

	var wg sync.WaitGroup
	wg.Add(2)

	//生产者协程
	go func() {
		defer wg.Done()
		for k := 0; k < capacity; k++ {
			mu.Lock()
			for len(queue) == capacity {
				cond.Wait()
			}

			queue = append(queue, k)
			fmt.Println("Produce:", k)

			if len(queue) == 1 {
				cond.Signal()
			}
			mu.Unlock()
		}
	}()

	//消费者协程
	go func() {
		defer wg.Done()
		for i := 0; i < capacity*2; i++ {
			mu.Lock()
			for len(queue) == 0 {
				cond.Wait()
			}
			item := queue[0]
			queue = queue[1:]
			fmt.Println("Consume:", item)

			if (len(queue)) == capacity-1 {
				cond.Signal()
			}
			mu.Unlock()
		}
	}()

	wg.Wait()
}
